:- module(lc_database_impl,
	[
	    (:=)/2,
	     resource_name_to_key/2,
	     ditem_name_to_key/2,
	     resource_key_to_name/2,
	     ditem_key_to_name/2,
	     amos_data_arity/1,
	     get_package/7,
	     d_item/3,
	     s_item/7,
	     r_f/1,
	     a_z_f/1,
	     a_a_f/1,
	     term_desc/3,
	     term_desc_keys/3,
	     gen_term_desc/0,
	     make_backup/0,
	     db_update/0
	],
	[persdb]).

:- include(search(package_ops)).
:- use_module(amos(configuration), [pers_data_dir/1, db_dir_perms/1, db_file_perms/1]).

:- use_module(library(sort), [sort/2]).
:- use_module(library(aggregates), [findall/3]).
:- use_module(library(lists), [append/3]).

%%kludge to make it work in ciao 1.9 with old persdb.
persistent_dir(conectadb, X, DirPerms, FilePerms) :- 
	pers_data_dir(X),
	db_dir_perms(DirPerms),
	db_file_perms(FilePerms).
%%
persistent_dir(conectadb, X) :- 
	pers_data_dir(X).

% persistent_dir(amosdb, './').

:- persistent(s_item/7,conectadb).
:- persistent(d_item/3,conectadb).
amos_data_arity(7).

a_z_f(P) :- persdbrt:assertz_fact(P).

a_a_f(P) :- persdbrt:asserta_fact(P).

r_f(P) :- persdbrt:retract_fact(P).

':='(Pkg,Precs ==> Posts):-
	s_item(Pkg,Posts0,Precs0,_,_,_,_),
	sort(Precs0,Precs),
	sort(Posts0,Posts).

%% There are no keys in temporary database.

get_package(PkgName,Idtags,Req,Link,Desc,Size,Lic):-
	s_item(PkgName,Idtags,Req,Link,Desc,Size,Lic).

resource_name_to_key(A,A).

ditem_name_to_key(A,A).

resource_key_to_name(A,A).

ditem_key_to_name(A,A).

term_desc(Term, Desc, GenList):-
	d_item(Term, Desc, GenList).

term_desc_keys(Term, Desc, GenList):-
	d_item(Term, Desc, GenList).

gen_term_desc:-
	% Add new dictionary terms that appear in s_item/7 or 
        % in the generalization list of other terms
	findall([Posts0,Precs0,Gens0], 
             ( s_item(_,Posts0,Precs0,_,_,_,_) 
             ; d_item(_,_,Gens0)
	     ), LLList),
	flatten(LLList,List),
	sort(List,SList),
	assert_all_d_item(SList).

flatten([],[]).
flatten([M|Ls],Flattened):-
	( list(M) ->
	  flatten(M,MFlattened),
	  flatten(Ls,LsFlattened),
	  append(MFlattened,LsFlattened,Flattened)
	; arg(1,M,MItem) ->       %% for in() and out() terms
	  flatten(Ls,LsFlattened),
	  Flattened = [MItem | LsFlattened]
	; flatten(Ls,LsFlattened),
	  Flattened = [M | LsFlattened]
	).

assert_all_d_item([]).
assert_all_d_item([D|Ds]):-
	( d_item(D, _, _) ->
	    true
	; 
	    ( 
		atom_concat('in(',Rest,D) -> 
		atom_concat(Item,')',Rest),
		atom_concat('The capability to read ',Item,Dsc)
	    ;
		atom_concat('out(',Rest,D) -> 
		atom_concat(Item,')',Rest),
		atom_concat('The capability to write ',Item,Dsc)
	    ;
		Dsc = ''
	    ),
	    persdbrt:assertz_fact(d_item(D, Dsc, []))
	),
	assert_all_d_item(Ds).

retract_all(Fact):-
	repeat,
	( persdbrt:retract_fact(Fact) ->
	  fail
	; true).


db_update:-
	update_files([s_item/7,d_item/3]).

% ---------------------------------------------------------------------------
% Backup of persistent databases
% ---------------------------------------------------------------------------

:- use_module(library(terms)).
:- use_module(library(streams)).
:- use_module(library(read)).
:- use_module(library(system), 
        [
            time/1,
            make_directory/1,
            make_dirpath/1,
            file_exists/1]).
:- use_module(library('make/system_extra'), [copy_file/2]).

%% How can we determine from persdb where each predicate is stored in?
s_item_file_name('s_item_7.pl').
d_item_file_name('d_item_3.pl').
database_dir_name('lc_database_impl').
backup_dir_name('Backup').

make_backup :-
        %
        s_item_file_name(PackFileName),
        d_item_file_name(DicFileName),
        database_dir_name(DBDirName),
        backup_dir_name(BackupDir),
        pers_data_dir(Where),
        %
        atom_concat([Where, /, DBDirName, /, PackFileName], PackFile),
        atom_concat([Where, /, DBDirName, /, DicFileName], DicFile),
        %
        atom_concat([Where, /, BackupDir], WholeBackDir),
       ( file_exists(WholeBackDir) -> true ; make_dirpath(WholeBackDir)),
        %
        %  This is to timestamp new versions of the database
        time(WhenNum),
        atom_number(WhenAt, WhenNum),
        atom_concat([WholeBackDir, /, PackFileName, -, WhenAt], BackPackFile),
        atom_concat([WholeBackDir, /, DicFileName, -, WhenAt],  BackDicFile),
        %
       ( file_exists(PackFile) -> copy_file(PackFile, BackPackFile) ; true ),
       ( file_exists(DicFile) -> copy_file(DicFile, BackDicFile) ; true ).
        
